package com.young.springboot.schedule;

import com.young.common.Config;
import com.young.config.YoungScheduleClientPropertyLocator;
import com.young.job.JobNode;
import com.young.job.ScheduleServerInstanceDO;
import com.young.rpc.DoJobService;
import com.young.rpc.ServerBootStrap;
import com.young.rpc.http.DefaultScheduleHttpClient;
import com.young.rpc.http.ScheduleHttpClient;
import com.young.scheduler.grpc.VClientSheduleServiceGrpc;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Configuration
@EnableConfigurationProperties(YoungSchedulerProperties.class)
public class YoungScheduleAutoConfiguration {

    @Autowired
    private YoungSchedulerProperties youngSchedulerProperties;

    @Autowired
    private Environment environment;


    @Bean
    @ConditionalOnMissingBean
    public JobNode jobNode(ScheduleHttpClient scheduleHttpClient, YoungScheduleClientPropertyLocator youngScheduleClientPropertyLocator) {

        if (youngSchedulerProperties.getCorePoolSize() != 0) {
            Config.scheduleThreadInitCount = youngSchedulerProperties.getCorePoolSize();
        }

        if (youngSchedulerProperties.getMaxPoolSize() != 0) {
            Config.scheduleThreadMaxCount = youngSchedulerProperties.getMaxPoolSize();
        }

        List<ScheduleServerInstanceDO> scheduleServerInstances = scheduleServerInstances(youngScheduleClientPropertyLocator);

        JobNode jobNode = new JobNode();

        String appName = youngSchedulerProperties.getAppName();

        if (appName == null) {
            appName = environment.getProperty("spring.application.name");
        }

        jobNode.setAppName(appName);
        jobNode.setDoJobServicePort(youngSchedulerProperties.getServicePort());
        jobNode.setScheduleHttpClient(scheduleHttpClient);
        jobNode.setServerNodesDefault(scheduleServerInstances);
        return jobNode;
    }

    /**
     * 得到 schedule server 节点列表
     * @param youngScheduleClientPropertyLocator
     * @return
     */
    private List<ScheduleServerInstanceDO> scheduleServerInstances(YoungScheduleClientPropertyLocator youngScheduleClientPropertyLocator) {
        String serverNodesStr = youngScheduleClientPropertyLocator.getProperty("yschedule.server.cluster.nodes", String.class);

        if(StringUtils.isBlank(serverNodesStr)) {
            throw new IllegalArgumentException("yschedule server 列表不能为空");
        }

        String[] serverNodes = serverNodesStr.split(",");
        return Arrays.asList(serverNodes).stream()
                .map(serverNode->{
                    String[] serverMeta = serverNode.split(":");
                    ScheduleServerInstanceDO scheduleServerInstanceDO = new ScheduleServerInstanceDO();
                    scheduleServerInstanceDO.setIp(serverMeta[0]);
                    scheduleServerInstanceDO.setPort(Integer.valueOf(serverMeta[1]));
                    return scheduleServerInstanceDO;
                }).collect(Collectors.toList());
    }


    @Bean(initMethod = "start",destroyMethod = "close")
    @ConditionalOnMissingBean
    public ScheduleHttpClient scheduleHttpClient(){
        return new DefaultScheduleHttpClient();
    }

    /*@Bean
    @ConditionalOnMissingBean
    public VClientSheduleServiceGrpc.VClientSheduleServiceImplBase clientScheduleService(){
        return new DoJobService();
    }

    @Bean(initMethod = "init")
    @ConditionalOnMissingBean
    public ServerBootStrap serverBootStrap(VClientSheduleServiceGrpc.VClientSheduleServiceImplBase clientScheduleService) {

        ServerBootStrap bootStrap = new ServerBootStrap();
        bootStrap.setClientScheduleService(clientScheduleService);
        return bootStrap;
    }*/

    /**
     * client sdk 环境配置文件加载
     * @return
     */
    @Bean
    public YoungScheduleClientPropertyLocator vkScheduleClientPropertyLocator() {
        return new YoungScheduleClientPropertyLocator(environment);
    }

}
